using System.Collections.Generic;

namespace OracleInternal.SqlAndPlsqlParser.RuleProcessors
{
	internal static class OracleMbEarleyRuleMultiProcessor
	{
		public static event OracleMbEarleyRuleMultiProcessorPrePostProcessingDelegate Preprocess;

		public static event OracleMbEarleyRuleMultiProcessorPrePostProcessingDelegate Postprocess;

		static OracleMbEarleyRuleMultiProcessor()
		{
		}

		public static object ProcessNodeRules(ParseNode pn, int startRuleIndex, int endRuleIndex, OracleMbEarleyParserMultiContext ctx)
		{
			if (OracleMbEarleyRuleMultiProcessor.Preprocess != null)
			{
				OracleMbEarleyRuleMultiProcessor.Preprocess(pn, ctx);
			}
			if (pn == null || pn.m_vRulesUsed == null)
			{
				return null;
			}
			object result = null;
			Dictionary<int, List<OracleMbEarleyRuleMultiProcessorToken>> ruleProcessors = ctx.RuleProcessorTable.RuleProcessors;
			if (endRuleIndex == -1)
			{
				endRuleIndex = pn.m_vRulesUsed.Count;
			}
			bool flag = pn != ctx.CurrentParseNode;
			ParseNode currentParseNode = null;
			int currentRuleIndex = 0;
			if (flag)
			{
				currentParseNode = ctx.CurrentParseNode;
				currentRuleIndex = ctx.CurrentRuleIndex;
				ctx.CurrentParseNode = pn;
			}
			int num;
			for (num = startRuleIndex; num < endRuleIndex; num++)
			{
				ctx.CurrentRuleIndex = num;
				int key = pn.m_vRulesUsed[num];
				if (ruleProcessors.TryGetValue(key, out var value))
				{
					foreach (OracleMbEarleyRuleMultiProcessorToken item in value)
					{
						result = item.m_vMultiProcessor(ctx, item.m_vRuleMatchPosition);
					}
				}
				num = ctx.CurrentRuleIndex;
			}
			if (flag)
			{
				ctx.CurrentRuleIndex = currentRuleIndex;
				ctx.CurrentParseNode = currentParseNode;
			}
			else
			{
				ctx.CurrentRuleIndex = endRuleIndex;
			}
			if (OracleMbEarleyRuleMultiProcessor.Postprocess != null)
			{
				OracleMbEarleyRuleMultiProcessor.Postprocess(pn, ctx);
			}
			return result;
		}

		public static object TraverseAndProcessNodeSubtreeRules(ParseNode pn, OracleMbEarleyParserMultiContext ctx, Dictionary<int, List<OracleMbEarleyRuleMultiProcessorToken>> rpd)
		{
			if (pn == null)
			{
				return null;
			}
			bool flag = false;
			object result = null;
			if (pn.m_vRulesUsed != null)
			{
				foreach (int item in pn.m_vRulesUsed)
				{
					if (rpd.ContainsKey(item))
					{
						flag = true;
						break;
					}
				}
			}
			if (flag)
			{
				ParseNode currentParseNode = ctx.CurrentParseNode;
				int currentRuleIndex = ctx.CurrentRuleIndex;
				ctx.CurrentParseNode = pn;
				ctx.CurrentRuleIndex = 0;
				result = ProcessNodeRules(pn, 0, -1, ctx);
				ctx.CurrentRuleIndex = currentRuleIndex;
				ctx.CurrentParseNode = currentParseNode;
				return result;
			}
			List<ParseNode> list = pn.Children();
			if (list == null)
			{
				return null;
			}
			foreach (ParseNode item2 in list)
			{
				result = TraverseAndProcessNodeSubtreeRules(item2, ctx, rpd);
			}
			return result;
		}

		public static object ProcessSubtreeRules(ParseNode pn, int startRuleIndex, int endRuleIndex, OracleMbEarleyParserMultiContext ctx)
		{
			if (pn == null || pn.m_vRulesUsed == null)
			{
				return null;
			}
			object result = null;
			Dictionary<int, List<OracleMbEarleyRuleMultiProcessorToken>> ruleProcessors = ctx.RuleProcessorTable.RuleProcessors;
			if (endRuleIndex == -1)
			{
				endRuleIndex = pn.m_vRulesUsed.Count;
			}
			bool flag = pn != ctx.CurrentParseNode;
			ParseNode currentParseNode = null;
			int currentRuleIndex = 0;
			if (flag)
			{
				currentParseNode = ctx.CurrentParseNode;
				currentRuleIndex = ctx.CurrentRuleIndex;
				ctx.CurrentParseNode = pn;
			}
			Queue<ParseNode> queue = new Queue<ParseNode>();
			queue.Enqueue(pn);
			int currentRuleIndex2 = startRuleIndex;
			int num = endRuleIndex;
			while (queue.Count > 0)
			{
				ParseNode parseNode2 = (ctx.CurrentParseNode = queue.Dequeue());
				if (num == -1)
				{
					num = parseNode2.m_vRulesUsed.Count;
				}
				bool flag2 = false;
				ctx.CurrentRuleIndex = currentRuleIndex2;
				while (ctx.CurrentRuleIndex < num)
				{
					int key = parseNode2.m_vRulesUsed[ctx.CurrentRuleIndex];
					if (ruleProcessors.TryGetValue(key, out var value))
					{
						flag2 = true;
						foreach (OracleMbEarleyRuleMultiProcessorToken item in value)
						{
							result = item.m_vMultiProcessor(ctx, item.m_vRuleMatchPosition);
						}
					}
					ctx.CurrentRuleIndex++;
				}
				if (!flag2)
				{
					foreach (ParseNode item2 in parseNode2.Children())
					{
						if (item2.m_vRulesUsed != null)
						{
							queue.Enqueue(item2);
						}
					}
				}
				currentRuleIndex2 = 0;
				num = -1;
			}
			if (flag)
			{
				ctx.CurrentRuleIndex = currentRuleIndex;
				ctx.CurrentParseNode = currentParseNode;
			}
			else
			{
				ctx.CurrentRuleIndex = endRuleIndex;
			}
			return result;
		}
	}
}
